package com.ruoyi.web.api;

import com.alibaba.fastjson2.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.wx.PayService;
import com.ruoyi.common.wx.StreamUtils;
import com.ruoyi.common.wx.WxPayDTO;
import com.ruoyi.common.wx.WxPayProperties;
import com.ruoyi.system.domain.AiOrder;
import com.ruoyi.system.domain.vo.AiOrderReqVo;
import com.ruoyi.system.service.IAiOrderService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付相关接口
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/wechat/pay")
public class ApiWechatPayController {
    private static final Logger log = LoggerFactory.getLogger(ApiWechatPayController.class);
    @Autowired
    private PayService payService;
    @Autowired
    private WxPayProperties wxPayProperties;
    @Autowired
    private IAiOrderService orderService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysConfigService sysConfigService;

    @GetMapping("/nativePay")
    @ApiOperation(value = "微信native下单,返回支付二维码")
    public Object nativePay(@RequestParam("orderNo") String orderNo) {
        //todo 业务操作-根据订单编号查询订单信息
        //将订单信息中的数据存到WxPayDTO
        WxPayDTO payDTO = new WxPayDTO();
        payDTO.setBody("商品描述");
        //订单总金额，单位为分
        payDTO.setTotalFee(1);
        //支付回调地址
        payDTO.setNotifyUrl(wxPayProperties.getNotifyUrl());
        //商品订单编号
        payDTO.setOutTradeNo(orderNo);
        //获取时间
        Date date = new Date();
        String timeStart = DateUtil.formatDateToString(date, "yyyyMMddHHmmss");
        //结束时间设置在30分钟后
        String timeExpire = DateUtil.formatDateToString(DateUtil.addMinutesToDate(date, 30), "yyyyMMddHHmmss");
        //交易起始时间
        payDTO.setTimeStart(timeStart);
        //交易结束时间
        payDTO.setTimeExpire(timeExpire);
        Object url = payService.transactions(payDTO, WxPayConstants.TradeType.NATIVE);
        return url;
    }

    @Transactional
    @PostMapping("/jsapiPay")
    @ApiOperation(value = "微信JSAPI下单,返回JS支付相关配置")
    public Object jsapiPay() {
        //todo 业务操作-根据订单编号查询订单信息
        // 暂时先合并一起，直接下单支付，前端暂时未有产品相关信息展示
        Integer orderAmount = Integer.parseInt(sysConfigService.selectConfigByKey("ai.order.amount"));
        String body = "AI价值导航服务费";
        String orderNo = IdUtils.fastSimpleUUID();
        Long userId = SecurityUtils.getUserId();
        AiOrder order = new AiOrder();
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setOrderType("AI服务");
        order.setOrderAmount(orderAmount);
        order.setBody(body);
        orderService.insertAiOrder(order);

        SysUser user = sysUserService.selectUserById(userId);
        String openId = user.getUserName();
        //将订单信息中的数据存到WxPayDTO
        WxPayDTO payDTO = new WxPayDTO();
        payDTO.setOutTradeNo(orderNo);
        payDTO.setBody(body);
        //订单总金额，单位为分
        payDTO.setTotalFee(orderAmount);
        //支付回调地址
        payDTO.setNotifyUrl(wxPayProperties.getNotifyUrl());
        //获取时间
        Date date = new Date();
        String timeStart = DateUtil.formatDateToString(date, "yyyyMMddHHmmss");
        //结束时间设置在30分钟后
        String timeExpire = DateUtil.formatDateToString(DateUtil.addMinutesToDate(date, 30), "yyyyMMddHHmmss");
        //交易起始时间
        payDTO.setTimeStart(timeStart);
        //交易结束时间
        payDTO.setTimeExpire(timeExpire);
        //todo jsapi下单需要用户的openid
        payDTO.setOpenId(openId);
        return payService.transactions(payDTO, WxPayConstants.TradeType.JSAPI);
    }

    @GetMapping("/h5Pay")
    @ApiOperation(value = "微信H5下单,返回跳转链接")
    public Object h5Pay(@RequestParam("orderNo") String orderNo, HttpServletRequest request) {
        //todo 业务操作-根据订单编号查询订单信息

        //将订单信息中的数据存到WxPayDTO
        WxPayDTO payDTO = new WxPayDTO();
        payDTO.setBody("商品描述");
        //订单总金额，单位为分
        payDTO.setTotalFee(1);
        //支付回调地址
        payDTO.setNotifyUrl(wxPayProperties.getNotifyUrl());
        payDTO.setOutTradeNo("商户订单号");
        //获取时间
        Date date = new Date();
        String timeStart = DateUtil.formatDateToString(date, "yyyyMMddHHmmss");
        //结束时间设置在30分钟后
        String timeExpire = DateUtil.formatDateToString(DateUtil.addMinutesToDate(date, 30), "yyyyMMddHHmmss");
        //交易起始时间
        payDTO.setTimeStart(timeStart);
        //交易结束时间
        payDTO.setTimeExpire(timeExpire);
        //todo H5下单需要用户的用户的客户端IP
        String remoteAddr = request.getRemoteAddr();
        payDTO.setPayerClientIp(remoteAddr);
        return payService.transactions(payDTO, WxPayConstants.TradeType.JSAPI);
    }

    @ApiOperation(value = "微信支付回调")
    @PostMapping("/notify")
    public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
        ServletInputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            String notifyXml = StreamUtils.inputStream2String(inputStream, "utf-8");
            log.info(notifyXml);
            // 解析返回结果
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyXml);
            String jsonString = JSONObject.toJSONString(notifyMap);
            log.info("微信支付回调返回结果：{}", jsonString);
            // 判断支付是否成功
            if ("SUCCESS".equals(notifyMap.get("result_code"))) {
                String outTradeNo = notifyMap.get("out_trade_no").toString(); // 商户订单号
                String totalFee = notifyMap.get("total_fee").toString(); // 订单总金额，单位为分
                String payType = notifyMap.get("trade_type").toString(); // 交易类型：JSAPI、NATIVE、APP
                String transactionId = notifyMap.get("transaction_id").toString(); // 微信支付订单号-三方交易号
                //todo 修改订单状态
                AiOrder order = orderService.selectAiOrderByOrderNo(outTradeNo);
                order.setStatus(1); // 支付成功
                order.setPayAmount(Integer.parseInt(totalFee));
                order.setPayType(payType);
                order.setTradeNo(transactionId);
                order.setPayTime(new Date());
                orderService.updateAiOrder(order);

                // 支付成功：给微信发送我已接收通知的响应 创建响应对象
                Map<String, String> returnMap = new HashMap<>();
                returnMap.put("return_code", "SUCCESS");
                returnMap.put("return_msg", "OK");
                String returnXml = WXPayUtil.mapToXml(returnMap);
                response.setContentType("text/xml");
                log.info("支付成功");
                return returnXml;
            } else {
                //保存回调信息,方便排除问题
            }
            // 创建响应对象：微信接收到校验失败的结果后，会反复的调用当前回调函数
            Map<String, String> returnMap = new HashMap<>();
            returnMap.put("return_code", "FAIL");
            returnMap.put("return_msg", "");
            String returnXml = WXPayUtil.mapToXml(returnMap);
            response.setContentType("text/xml");
            log.info("校验失败");
            return returnXml;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
